package com.example.petplanet.websocket;

import com.alibaba.fastjson2.JSON;
import com.example.petplanet.config.WebSocketConfigurator;
import com.example.petplanet.domain.Message;
import com.example.petplanet.service.OfflineMessageService;
import com.example.petplanet.service.UserService;
import com.example.petplanet.util.MessageUtils;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chatNotify",configurator = WebSocketConfigurator.class)
@Component
@CrossOrigin
public class ChatNotifyEndpoint {

    // 保存在线的用户，key为userid，value为 Session 对象
    private static final Map<Long, Session> onlineUsers = new ConcurrentHashMap<>();

    private static OfflineMessageService offlineMessageService;


    @Autowired
    public void setOfflineMessageService(OfflineMessageService offlineMessageService, UserService userService) {
        ChatNotifyEndpoint.offlineMessageService = offlineMessageService;
    }

    @OnOpen
    public void onOpen(Session session,EndpointConfig config) {
        String userIdStr = (String) config.getUserProperties().get("userId");
        if (userIdStr != null) {
            long userId = Long.parseLong(userIdStr);
            // 关闭旧的连接，token已失效的连接
            deleteOldSession(userId,session);
            onlineUsers.put(userId, session);
            //加入离线消息
            List<Message> messages = offlineMessageService.getMessagesByUserId(userId);
            if(messages!=null){
                for (Message message : messages) {
                    String messageToSend = MessageUtils.getResultMessage(message);
                    try {
                        offlineMessageService.deleteMessage(message.getId());
                        session.getBasicRemote().sendText(messageToSend);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 通知所有用户，当前用户上线了
            String message = MessageUtils.getSystemResultMessage(getOnlineUsers());
            broadcastOnlineUsers(message);
        }
    }

    //10mb
    @OnMessage(maxMessageSize = 10485760)
    public void onMessage(String message,Session SendSession) {
        try {
            // 将消息推送给指定的用户
            Message msg = JSON.parseObject(message, Message.class);
            // 获取消息接收方的消息内容和属性
            String tempMessage = (String) msg.getMessage();
            // 获取消息接收方用户对象的 session 对象
            long toUserId = msg.getToUserId();
            Session receiveSession = onlineUsers.get(toUserId);
            // 获取发送方的用户名userid
            //后续处理异常，可能为-1
            long sendUserUserid = getUserIdBySession(SendSession);
            //不用发送给自己
            if(sendUserUserid ==toUserId) return;
            // 组装并发送消息给消息接收方
            String messageToSend = MessageUtils.getResultMessage(toUserId,sendUserUserid, tempMessage,msg.getType());
            if (receiveSession == null){
                //加入离线消息
                offlineMessageService.addOfflineMessage(msg,sendUserUserid);
            }else{
                receiveSession.getBasicRemote().sendText(messageToSend);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        long userId = getUserIdBySession(session);
        if (userId != -1) {
            Session remove = onlineUsers.remove(userId);
            if (remove != null) {
                remove.close();
            }
            session.close();
        }
        // 通知所有用户，该用户下线了
        String message = MessageUtils.getSystemResultMessage(getOnlineUsers());
        broadcastOnlineUsers(message);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("Error occurred in session: " + session.getId());
        throwable.printStackTrace();
    }

    private Set<Long> getOnlineUsers() {
        return onlineUsers.keySet();
    }

    private void broadcastOnlineUsers(String message) {
        try {
            Set<Map.Entry<Long, Session>> entries = onlineUsers.entrySet();

            for (Map.Entry<Long, Session> entry : entries) {
                // 获取到所有用户对应的 session 对象
                Session session = entry.getValue();

                // 使用 getBasicRemote() 方法发送同步消息
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    //通过session获取用户的userid
    private long getUserIdBySession(Session session) {
        for (Map.Entry<Long, Session> entry : onlineUsers.entrySet()) {
            if (entry.getValue().equals(session)) {
                return entry.getKey();
            }
        }
        return -1; // 如果没有找到对应的userid，返回 -1
    }


    private void deleteOldSession(long userId, Session newSession) {
        for (Map.Entry<Long, Session> entry : onlineUsers.entrySet()) {
            if (entry.getKey().equals(userId) && !entry.getValue().equals(newSession)) {
                Session oldSession = entry.getValue();
                try {
                    oldSession.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "新的连接已建立，旧连接关闭"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
                onlineUsers.remove(userId);
                break;
            }
        }
    }


}
